import {Injectable} from '@angular/core';
import {HttpService} from "./http.service";
import {HttpClient} from "@angular/common/http";
import {AccountDTO, AccountFrom, EncodedToken} from "../model/account-dto";
import {Result} from "../model/restful";
import {NzMessageService} from 'ng-zorro-antd/message';
import {EncryptService} from "./encrypt.service";
import {UserService} from "./user.service";

@Injectable({
  providedIn: 'root'
})
export class AccountService {

  constructor(
    private server: HttpService,
    private httpClient: HttpClient,
    private encryptor: EncryptService,
    private userService: UserService,
    private message: NzMessageService
  ) {
  }

  login(form: AccountFrom, handle: (success: boolean) => void) {
    const ref = this
    this.reqEncodedToken(handle, (token) => {
      const accountDto = this.prepareDto(form, token)
      const observer = {
        next(rsl: Result<string>) {
          handle(rsl.success)
          if (!rsl.success) {
            ref.message.warning(rsl.message)
          } else {
            const jwt = rsl.data!!
            ref.userService.login(jwt)
          }
        },
        error(e: any) {
          ref.message.error('登录异常, 请稍后重试')
          console.log(e)
        },
        complete() {
          handle(false)
        }
      }
      ref.httpClient.post<Result<any>>(ref.server.baseUrl() + '/account/login', accountDto)
        .subscribe(observer)
    })
  }

  register(form: AccountFrom, handle: (success: boolean) => void) {
    const ref = this
    this.reqEncodedToken(handle, (token) => {
      const accountDto = this.prepareDto(form, token)
      const observer = {
        next(rsl: Result<string>) {
          if (!rsl.success) {
            ref.message.warning(rsl.message)
          } else {
            const jwt = rsl.data!!
            ref.userService.login(jwt)
          }
          handle(rsl.success)
        },
        error(e: any) {
          ref.message.error('网络错误')
          console.log(e)
        },
        complete() {
          handle(false)
        }
      }

      ref.httpClient.post<Result<any>>(ref.server.baseUrl() + '/account/register', accountDto)
        .subscribe(observer)
    })
  }

  private prepareDto(form: AccountFrom, token: EncodedToken): AccountDTO {
    const encodedPass = this.encryptor.encodeByPublicKey(form.password, token.publicKey)
    return {
      username: form.username,
      password: encodedPass,
      clientId: token.clientId,
      token: form.token
    }
  }

  private reqEncodedToken(
    errHandle: (success: boolean) => void,
    handle: (token: EncodedToken) => void
  ) {
    const ref = this
    const observer = {
      next(r: Result<EncodedToken>) {
        console.log(r)
        if (r.success) {
          const encodedToken = r.data!
          handle(encodedToken)
        } else {
          ref.message.error(r.message)
          console.log(r)
        }
      },
      error(e: any) {
        errHandle(false)
        ref.message.error('网络错误')
        console.log(e)
      },
    }
    this.httpClient.get<Result<EncodedToken>>(this.server.baseUrl() + '/account/')
      .subscribe(observer)
  }
}
